package kevin.study.zephyr.domain.dao.db4o;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Date;

import kevin.study.zephyr.domain.dao.IGenericDAO;
import kevin.study.zephyr.domain.dao.soda.ZQuery;
import kevin.study.zephyr.domain.model.base.Base;

import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
import com.db4o.query.Query;

/**
 * @author Kevin.Huang
 * @createtime 2007-12-12
 * @param <K>
 */
public class DB4ODAO< K > implements IGenericDAO< K > {

	/**
	 *
	 */
	@SuppressWarnings("unchecked")
	protected Class persistentClass;

	/**
	 * @return the persistentClass
	 */
	@SuppressWarnings("unchecked")
	public Class getPersistentClass() {
		return persistentClass;
	}

	/**
	 * @param persistentClass
	 *            the persistentClass to set
	 */
	public void setPersistentClass(Class< K > persistentClass) {
		this.persistentClass = persistentClass;
	}

	/**
	 * db4o的session
	 */
	protected ObjectContainer db;

	public void delete(K entity) {
		db.delete(entity);
		db.commit();
	}

    public void delete(Serializable id) {
        delete(findById(id));
    }

    @SuppressWarnings("unchecked")
	public List< K > findAll() {
		return db.query(getPersistentClass());
	}

	public List< K > findByExample(K exampleInstance) {
		return db.get(exampleInstance);
	}

	@SuppressWarnings("unchecked")
	public List< K > findByQuery(ZQuery query) {
		Query q = db.query();
		ZQueryParse zqp = new ZQueryParse();
		return zqp.parseZQuery(query, q).execute();
	}

	public K findById(Serializable id) {
		Base obj;
		try {
			obj = (Base) getPersistentClass().newInstance();
		} catch (InstantiationException e) {
			// XXX 记录异常
			throw new RuntimeException("Domain Model is ERROR!", e);
		} catch (IllegalAccessException e) {
			// XXX 记录异常
			throw new RuntimeException("Domain Model is ERROR!", e);
		}
        obj.clear();
		obj.setUuid((String) id);
		ObjectSet< K > result = db.get(obj);
		if (result.hasNext()) {
			return result.next();
		} else {
			return null;
		}
	}

	public List< K > findByQuery(ZQuery query, int index, int count) {
		List< K > result = findByQuery(query);
		List< K > returnObjs = new ArrayList< K >();
		Integer startIndex = index;
		Integer pageCount = count;
		if (startIndex < 1) {
			startIndex = 1;
		}
		if (pageCount < 0) {
			pageCount = 0;
		}
		for (int i = (startIndex - 1) * pageCount; (i < startIndex * pageCount) && (i < result.size()); i++) {
			returnObjs.add(result.get(i));
		}
		return returnObjs;
	}

	public Integer findCountByQuery(ZQuery query) {
		return findByQuery(query).size();
	}

	public K saveAndUpdate(K entity) {
		Base obj = (Base) findById(((Base) entity).getUuid());
		if (obj != null) {
            obj.setModifyTime(new Date());
			db.ext().bind(entity, db.ext().getID(obj));
		}
		db.set(entity);
		db.commit();
		return entity;
	}

    /**
     *
     * @return the db
     */
	public ObjectContainer getDb() {
		return db;
	}

    /**
     *
     * @param db the db
     */
	public void setDb(ObjectContainer db) {
		this.db = db;
	}

}
